﻿
#include"CommandHandler.hpp"
#include"MapApp.hpp"
#include"Service.hpp"
#include"SessionMgr.hpp"
#include"../Base/Network/BinaryDispatch.hpp"
#include"../Protocol/MapProtocol.hpp"
#include"rapidjson/document.h"
#include"rapidjson/stringbuffer.h"
#include"rapidjson/writer.h"
#include"SecIslSNMGR.hpp"
#include"SatelliteMGR.hpp"
#include"GnssMGR.hpp"
#include"../DataBase/EvSceneData.hpp"
#include"../Protocol/Seralize.hpp"
#include"../Base/Concurrency/TimeStamp.hpp"
#include<string>




namespace SC_SUN
{
    namespace Details
    {
        using namespace MMFNetwork;
        using namespace MMFSerialize;

        //解析网络消息
        template<typename T>
        void ParseMessage(MMFMessageHeader* pkg, T& msg)
        {
            char* data = pkg->mName + pkg->mNameBytes;
            SerialOutBuffer out(data, pkg->mDataBytes - (uint32_t(pkg->mName - (char*)pkg) + pkg->mNameBytes));
            out << msg;
        }

        //用于发送不同的数据
        //很多时候单一显控发起了某个操作，结果需同步到所有显控
        template<typename T>
        void SendMsgTo(MapApp& app, const std::shared_ptr<Session>& session, const char* msgName, T msg, bool isToAll = false)
        {
            uint32_t headLen = CalcMessageHeadLen(msgName);
            std::vector<char>& iBuff = app.GetSockService()->GetSerialInBuffer();
            MMFSerialize::SerialInBuffer iSBuff(iBuff.data() + headLen, (uint32_t)iBuff.size() - headLen);
            iSBuff >> msg;
            uint32_t total = FillMessageHead(iBuff, headLen, msgName, iSBuff.mPos);

            if (!isToAll)
                session->AsyncSend(iBuff.data(), total);
            else 
            {
                app.GetSockSessionMgr()->AsyncSendToAll(iBuff.data(), total);

            }
        }
    }

    CommandHandler::CommandHandler(MapApp& app, Service& service)
        : mApp(app)
        , mService(service)
    {

    }

    CommandHandler::~CommandHandler()
    {

    }

    bool CommandHandler::Start()
    {
        RegisterHandler();
        return true;
    }

    void CommandHandler::RegisterHandler()
    {
        using namespace MMFNetwork;
        using namespace MMFSerialize;
        using namespace rapidjson;
        using namespace Details;

        //卫星列表查询
        mService.Dispatcher()->RegisterCallback(SC_SATELLITE_LIST_MSG, [this](const std::shared_ptr<Session>& session, MMFMessageHeader* pkg){
            ScSatelliteListMSG msg = {};
            Details::ParseMessage(pkg, msg);

            //获取卫星编号列表
            const std::vector<std::string>& list = mApp.GetSatelliteMGR().GetSatelliteList();

            //填充消息数据
            Document d;
            d.SetArray();
            for (int i = 0; i < list.size(); i++)
            {
                Value v(kStringType);
                v.SetString(list[i].data(), list[i].length());
                d.PushBack(v, d.GetAllocator());
            }

            //数据转换成字符串
            StringBuffer buffer;
            Writer<StringBuffer> writer(buffer);
            d.Accept(writer);
            std::string jsonStr = buffer.GetString();

            //回消息
            msg.msg = std::string(jsonStr);
            SendMsgTo<ScSatelliteListMSG>(mApp, session, SC_SATELLITE_LIST_MSG, msg);
        });


        //卫星信息查询
        mService.Dispatcher()->RegisterCallback(SC_SATELLITE_MSG, [this](const std::shared_ptr<Session>& session, MMFMessageHeader* pkg){
            ScSatelliteMSG msg = {};
            Details::ParseMessage(pkg, msg);

            //获取参数
            Document doc;
            doc.Parse(msg.msg.data());
            std::string SAT_SN = doc.GetObj()["SAT_SN"].GetString();

            //获取卫星实体
            EvSatelliteData* sat = mApp.GetSatelliteMGR().GetSatellite(SAT_SN, mApp.GetSliceIdx());
            std::string jsonStr = SatelliteToJson(*sat);

            //回消息
            msg.msg = std::string(jsonStr);
            SendMsgTo<ScSatelliteMSG>(mApp, session, SC_SATELLITE_MSG, msg);
        });


        //卫星连接节点查询
        mService.Dispatcher()->RegisterCallback(SC_COLLECTION_MSG, [this](const std::shared_ptr<Session>& session, MMFMessageHeader* pkg){
            ScCollectionMSG msg = {};
            Details::ParseMessage(pkg, msg);

            //获取参数
            Document doc;
            doc.Parse(msg.msg.data());
            std::string SAT_SN = doc.GetObj()["SAT_SN"].GetString();

            //获取卫星实体
            EvSatelliteData* sat = mApp.GetSatelliteMGR().GetSatellite(SAT_SN, mApp.GetSliceIdx());

            //包装数据
            Document doc2;
            doc2.SetObject();

            Value parents(kArrayType);
            for (int i = 0; i < sat->Parents.size(); i++)
            {
                parents.PushBack(Value(sat->Parents[i].data(), doc2.GetAllocator()), doc2.GetAllocator());
            }

            Value children(kArrayType);
            for (int i = 0; i < sat->Children.size(); i++)
            {
                children.PushBack(Value(sat->Children[i].data(), doc2.GetAllocator()), doc2.GetAllocator());
            }

            doc2.AddMember(Value("parents", doc.GetAllocator()), parents, doc.GetAllocator());
            doc2.AddMember(Value("children", doc.GetAllocator()), children, doc.GetAllocator());

            //数据转换成字符串
            StringBuffer buffer;
            Writer<StringBuffer> writer(buffer);
            doc2.Accept(writer);
            std::string jsonStr = buffer.GetString();

            //回消息
            msg.msg = std::string(jsonStr);
            SendMsgTo<ScCollectionMSG>(mApp, session, SC_COLLECTION_MSG, msg);
        });


        //GNSS查询
        mService.Dispatcher()->RegisterCallback(SC_GNSS_MSG, [this](const std::shared_ptr<Session>& session, MMFMessageHeader* pkg){
            ScGnssMSG msg = {};
            Details::ParseMessage(pkg, msg);

            //获取参数
            Document doc;
            doc.Parse(msg.msg.data());
            std::string SAT_SN = doc.GetObj()["SAT_SN"].GetString();

            //获取数据
            EvGnssSNData* gnss = mApp.GnssMGR().GetGNSS(SAT_SN, mApp.GetSliceIdx());

            //回消息
            msg.msg = GnssToJson(*gnss);
            SendMsgTo<ScGnssMSG>(mApp, session, SC_GNSS_MSG, msg);
        });


        //卫星星间信息查询
        mService.Dispatcher()->RegisterCallback(SC_SEC_ISL_MSG, [this](const std::shared_ptr<Session>& session, MMFMessageHeader* pkg){
            ScSecIslMSG msg = {};
            Details::ParseMessage(pkg, msg);

            //获取参数
            Document doc;
            doc.Parse(msg.msg.data());

            //获取参数
            std::string SEC_ISL_SAT1 = doc.GetObj()["SEC_ISL_SAT1"].GetString();
            std::string SEC_ISL_SAT2 = doc.GetObj()["SEC_ISL_SAT2"].GetString();

            EvSecIslSNData* sec = mApp.SecIslSNMGR().GetBySatellite(SEC_ISL_SAT1, SEC_ISL_SAT2);

            //回消息
            msg.msg = SecISNToJson(*sec);
            SendMsgTo<ScSecIslMSG>(mApp, session, SC_SEC_ISL_MSG, msg);
        });


        //场景信息查询
        mService.Dispatcher()->RegisterCallback(SC_SCENE_MSG, [this](const std::shared_ptr<Session>& session, MMFMessageHeader* pkg){
            ScSceneMSG msg = {};
            Details::ParseMessage(pkg, msg);

            //数据获取
            EvSceneData sc = mApp.GetScene();
            Document doc  = sc.ObjToJsonObject();

            //数据转换成字符串
            StringBuffer buffer;
            Writer<StringBuffer> writer(buffer);
            doc.Accept(writer);
            std::string jsonStr = buffer.GetString();

            //回消息
            msg.msg = jsonStr;
            SendMsgTo<ScSceneMSG>(mApp, session, SC_SCENE_MSG, msg);
        });


        //时序推动
        mService.Dispatcher()->RegisterCallback(SC_TIME_MSG, [this](const std::shared_ptr<Session>& session, MMFMessageHeader* pkg){
            ScTimeMSG msg = {};
            Details::ParseMessage(pkg, msg);

            //解析协议
            Document doc;
            doc.Parse(msg.msg.data());
            uint32_t slice = doc.GetObj()["SLICE_IDX"].GetUint();

            //星间数据刷新
            mApp.setSliceIdx(slice);
            mApp.SecIslSNMGR().LoadBySlice(slice);

            //反消息
            SendMsgTo<ScTimeMSG>(mApp, session, SC_TIME_MSG, msg);
        });


        //场景选择
        mService.Dispatcher()->RegisterCallback(SC_SET_SCENE_MSG, [this](const std::shared_ptr<Session>& session, MMFMessageHeader* pkg){
            ScSetSceneMSG msg = {};
            Details::ParseMessage(pkg, msg);

            //设置场景信息
            std::chrono::microseconds start = MMF::TimeStamp::GetUsTime();
            mApp.setCurScene(msg.msg);
            mApp.GetSatelliteMGR().LoadData();
            mApp.GnssMGR().LoadData();
            mApp.SecIslSNMGR().LoadData();
            std::chrono::microseconds end = MMF::TimeStamp::GetUsTime();
            std::cout << "Scene Load Cost:" << (end - start).count() << "us" << std::endl;

            SendMsgTo<ScSetSceneMSG>(mApp, session, SC_SET_SCENE_MSG, msg);
        });


        //场景列表获取
        mService.Dispatcher()->RegisterCallback(SC_GET_SCENE_LIST_MSG, [this](const std::shared_ptr<Session>& session, MMFMessageHeader* pkg){
            ScGetSceneListMSG msg = {};
            Details::ParseMessage(pkg, msg);

            //获取场景信息
            msg.scenes  = mApp.GetSceneList();
            SendMsgTo<ScGetSceneListMSG>(mApp, session, SC_GET_SCENE_LIST_MSG, msg);
        });

        //获取场景时间信息
        mService.Dispatcher()->RegisterCallback(SC_GET_SCENE_TIME_INFO_MSG, [this](const std::shared_ptr<Session>& session, MMFMessageHeader* pkg){
            SceneTimeInfoMsg msg = {};
            Details::ParseMessage(pkg, msg);

            SceneTimeInfoMsg ret;
            double tmp = 0;
            mApp.GetSatelliteMGR().GetTimeAndStep(ret.mSatStep, tmp);
            mApp.GnssMGR().GetTimeAndStep(ret.mGNSSStep, ret.mGNSSTotal);
            mApp.SecIslSNMGR().GetTimeAndStep(ret.mSecStep, ret.mSecTotal);

            msg.mSatStep = ret.mSatStep;
            msg.mGNSSStep = ret.mGNSSStep;
            msg.mGNSSTotal = ret.mGNSSTotal;
            msg.mSecStep = ret.mSecStep;
            msg.mSecTotal = ret.mSecTotal;

            SendMsgTo<SceneTimeInfoMsg>(mApp, session, SC_GET_SCENE_TIME_INFO_MSG, msg);
        });
    }
}